package com.weixin.common.sftp;

import org.springframework.util.Assert;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * sftp multi host hostHolder
 *
 * @author zh
 */
public class HostHolder {
    private static final ThreadLocal<Record> THREAD_LOCAL = new ThreadLocal<>();
    private static Set<String> hostNames;

    public static LinkedHashMap<String, ClientProperties> initHostNames(LinkedHashMap<String, ClientProperties> clientPropertiesMap) {
        if (hostNames != null) {
            throw new UnsupportedOperationException("hostNames exists！");
        }
        hostNames = Collections.unmodifiableSet(clientPropertiesMap.keySet());
        return clientPropertiesMap;
    }

    /**
     * get all hostNames
     *
     * @return hostNames
     * @see ClientProperties#getHosts()
     */
    public static Set<String> hostNames() {
        Assert.notNull(hostNames, "hostNames must not be null ！");
        return hostNames;
    }

    /**
     * get filter hostNames
     *
     * @param predicate filter condition
     * @return hostNames
     */
    public static Set<String> hostNames(Predicate<String> predicate) {
        Assert.notNull(hostNames, "hostNames must not be null ！");
        return hostNames.stream().filter(predicate).collect(Collectors.toSet());
    }

    /**
     * switch host
     *
     * @param hostName host
     * @see ClientProperties#getHosts()
     */
    public static void changeHost(String hostName) {
        Assert.notNull(hostName, "hostNames must not be null ！");
        THREAD_LOCAL.set(new Record(hostName, true));
    }

    /**
     * switch host
     *
     * @param hostName  host
     * @param autoClose if true,host will be clear,when you invoke clear()
     * @see ClientProperties#getHosts()
     */
    public static void changeHost(String hostName, boolean autoClose) {
        Assert.notNull(hostName, "hostNames must not be null ！");
        THREAD_LOCAL.set(new Record(hostName, autoClose));
    }

    /**
     * clear threadLocal
     */
    public static void clearHost() {
        THREAD_LOCAL.remove();
    }

    protected static String getHostName() {
        Record record;
        Assert.notNull(record = THREAD_LOCAL.get(), "hostNames must not be null ！");
        return record.hostName;
    }

    /**
     * clear host by autoClose to judge
     */
    protected static void clear() {
        Record record;
        if ((record = THREAD_LOCAL.get()) != null && record.autoClose) {
            THREAD_LOCAL.remove();
        }
    }

    static class Record {
        String hostName;
        boolean autoClose;

        Record(String hostName, boolean autoClose) {
            this.hostName = hostName;
            this.autoClose = autoClose;
        }
    }
}
